package smstpl

import (
	"context"
	"gitee.com/bobo-rs/creative-framework/pkg/sms/models"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/innovideo-services/enums"
	"gitee.com/bobo-rs/innovideo-services/framework/dao"
	"gitee.com/bobo-rs/innovideo-services/framework/model"
	"gitee.com/bobo-rs/innovideo-services/framework/model/entity"
	"gitee.com/bobo-rs/innovideo-services/library/services/sms"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

// GetTemplateOutList 获取外部SMS平台模板列表
func (t *sSmsTpl) GetTemplateOutList(ctx context.Context, in model.SmsTemplateOutListInput) (out *model.SmsTemplateOutListOutput, err error) {
	out = &model.SmsTemplateOutListOutput{}

	// 获取数据
	err = t.OutModel().ScanOmitEmpty(ctx, g.Map{
		dao.SmsTemplateOut.Columns().VarAlias: in.Alias,
		dao.SmsTemplateOut.Columns().FromType: in.FromType,
	}, &out)
	if err != nil {
		return nil, err
	}

	// 是否存在
	if out == nil {
		return nil, gerror.New(`暂无数据`)
	}
	return
}

// SaveTemplateOut 保存平台SMS短信模板数据
func (t *sSmsTpl) SaveTemplateOut(ctx context.Context, out entity.SmsTemplateOut) error {
	if len(out.VarAlias) == 0 || len(out.FromType) == 0 || len(out.TemplateId) == 0 {
		return gerror.New(`模板变量、SMS服务平台、SMS平台模板ID不能为空`)
	}

	// 获取模板是否存在，存在则编辑
	if out.Id > 0 {
		outMap, _ := t.ProcessTemplateOutMapByAlias(ctx, out.FromType, out.VarAlias)
		if outMap != nil {
			out.Id = outMap[out.VarAlias].Id
		}
	}

	// 保存数据
	_, err := dao.SmsTemplateOut.Ctx(ctx).Save(out)
	if err != nil {
		return gerror.Wrapf(err, `保存外部平台模板数据失败%s`, err.Error())
	}
	return nil
}

// DeleteTemplateOutByVarAlias 根据短信模板变量上传外部平台模板数据
func (t *sSmsTpl) DeleteTemplateOutByVarAlias(ctx context.Context, varAlias enums.SmsAlias) error {
	if len(varAlias) == 0 {
		return gerror.New(`SMS模板不存在`)
	}
	_, err := dao.SmsTemplateOut.Ctx(ctx).
		Where(dao.SmsTemplateOut.Columns().VarAlias, varAlias).
		Delete()
	if err != nil {
		return gerror.Wrapf(err, `删除外部平台模板失败%s`, err.Error())
	}
	return nil
}

// ApplyOutFromTemplate 同步模板到外部平台
func (t *sSmsTpl) ApplyOutFromTemplate(ctx context.Context, tid uint, fromType string) error {
	// 获取模板数据
	item, err := t.ProcessTemplateDetailById(ctx, tid)
	if err != nil {
		return err
	}

	// 实例SMS服务
	smsService, err := sms.New().Ctx(ctx).Service()
	if err != nil {
		return err
	}

	// 发布请求参数
	params := models.AddSmsTemplateInput{
		TemplateName: item.Name,
		Content:      item.Name,
		SmsType:      uint64(item.SmsType),
		Remark:       item.Remark,
	}
	// 检测是否已存在关联平台模板
	if template_id, err := t.ProcessTemplateIdByAliasAndFrom(ctx, fromType, item.VarAlias); err == nil {
		params.TemplateId = *template_id
	}

	// 申请模板
	resp, err := smsService.Apply(params)
	if err != nil {
		return gerror.Wrapf(err, `同步平台[%s]模板%s`, fromType, err.Error())
	}

	// 保存模板数据
	return t.SaveTemplateOut(ctx, entity.SmsTemplateOut{
		TemplateId: resp.TemplateId,
		VarAlias:   item.VarAlias,
		FromType:   fromType,
	})
}

// SyncOutFromTemplateStatus 同步更新外部平台模板状态
func (t *sSmsTpl) SyncOutFromTemplateStatus(ctx context.Context, fromType string) error {
	var (
		list []model.SmsSyncOutTmplStatusItem
	)

	// 获取外部平台模板列表
	err := t.OutModel().Scan(ctx, g.Map{
		dao.SmsTemplateOut.Columns().FromType: fromType,
	}, &list)
	if err != nil {
		return err
	}

	// 数据是否存在
	if len(list) == 0 {
		return gerror.New(`外部平台模板不存在`)
	}

	// 获取外部平台模板
	smsService, err := sms.New().Ctx(ctx).Service()
	if err != nil {
		return err
	}

	// 获取外部平台所有模板数据
	outList, err := smsService.List(models.SmsTemplateListInput{
		Limit: uint64(len(list)),
	})
	if err != nil {
		return err
	}

	// 转换外部数据为MAP
	tmplMap, err := utils.NewArray(outList.Rows).Map(`template_id`)
	if err != nil {
		return err
	}

	// 格式数据
	for key, item := range list {
		// 断言模板结果
		if tmplResult, ok := tmplMap[item.TemplateId]; ok {
			if result, ok := tmplResult.(*models.SmsListResultItem); ok {
				item.OutTmplStatus = result.StatusText
			}
		}
		list[key] = item
	}

	// 更新SMS数据
	_, err = dao.SmsTemplateOut.Ctx(ctx).Save(list)
	if err != nil {
		return gerror.Wrapf(err, `更新外部平台模板状态失败%s`, err.Error())
	}
	return nil
}

// SendSmsOutFrom 发送短信-提交短信到第三方平台
func (t *sSmsTpl) SendSmsOutFrom(ctx context.Context, in model.SendOutFromSmsItem) error {
	if len(in.Mobile) == 0 {
		return gerror.New(`发送短信缺少手机号`)
	}

	// 获取短信模板内容
	item, err := t.GetTemplateByAlias(ctx, in.VarAlias)
	if err != nil {
		return err
	}

	// 实例短信服务
	smsService, err := sms.New().Ctx(ctx).Service()
	if err != nil {
		return err
	}

	// 发送短信
	resp, err := smsService.Send(in.Mobile, models.SendSmsInput{
		TemplateId:     item.TemplateId,
		Content:        utils.SmsReplaceVal(item.Content, in.TemplateParams...),
		TemplateParams: in.TemplateParams,
	})
	if err != nil {
		return gerror.Wrapf(err, `发送失败%s`, err.Error())
	}

	// 记录发送记录
	_ = t.SaveRecord(ctx, t.sendSmsResultHandler(ctx, model.SendSmsResultItem{
		SendSmsTemplateItem: in.SendSmsTemplateItem,
		CurrTemplateItem:    *item,
	}, *resp)...)
	return nil
}

// sendSmsResultHandler 短信发送结果处理
func (t *sSmsTpl) sendSmsResultHandler(ctx context.Context, item model.SendSmsResultItem, resp models.SendSmsResponse) []entity.SmsRecord {
	var (
		records = make([]entity.SmsRecord, 0, len(resp.Results))
		ip      = ghttp.RequestFromCtx(ctx).GetClientIp()
		content = utils.SmsReplaceVal(item.Content, item.TemplateParams...)
	)

	// 迭代处理发送结果
	for _, result := range resp.Results {
		records = append(records, entity.SmsRecord{
			Mobile:     result.Mobile,
			Code:       item.Code,
			TemplateId: item.TemplateId,
			Ip:         ip,
			SmsType:    uint(item.SmsType),
			SerialId:   result.SerialNo,
			Results:    result.Message,
			Content:    content,
		})
	}
	return records
}
